package material

import (
	"fmt"
	"gitee.com/bobo-rs/creative-framework/pkg/ifile"
	"gitee.com/bobo-rs/creative-framework/pkg/img"
	"gitee.com/bobo-rs/innovideo-services/library/models"
	"github.com/gogf/gf/v2/errors/gerror"
	"sync"
)

// MaterialDesignOverlays 处理多个素材模板合成图片
func (m *sMaterial) MaterialDesignOverlays(materials ...models.MaterialDesignOverlayItem) (out []models.MaterialDesignResultItem, err error) {
	if len(materials) == 0 {
		return nil, gerror.New(`缺少素材内容`)
	}
	var (
		// 限制并发通道
		semaphore  = make(chan struct{}, 10)
		resultChan = make(chan *models.MaterialDesignResultItem, len(materials)) // 开启收集设计结果通道
		errorChan  = make(chan error, len(materials))                            // 开启收集错误信息

		wg = sync.WaitGroup{}
	)

	// 并发处理数据
	for _, material := range materials {
		// 获取一个位置，没有则阻塞
		semaphore <- struct{}{}
		wg.Add(1)

		go func(mater models.MaterialDesignOverlayItem) {
			defer func() {
				// 释放
				<-semaphore
				wg.Done()
			}()
			// 处理图片合成
			item, err := m.ProcessSingleDesignOverlay(mater, nil)
			if err != nil {
				errorChan <- err // 记录到错误通道
				return
			}
			// 记录处理结果
			resultChan <- item
		}(material)
	}
	// 等待结束
	go func() {
		wg.Wait()
		close(errorChan)  // 释放关闭通道
		close(resultChan) // 释放结果
	}()

	// 获取处理结果
	out = make([]models.MaterialDesignResultItem, 0)
	for result := range resultChan {
		out = append(out, *result)
	}
	// 错误结果集
	if len(errorChan) > 0 {
		var errs []error
		for err = range errorChan {
			errs = append(errs, err)
		}
		err = fmt.Errorf("在合成图片过程中发生错误，详情如下：\n%+v", errs)
	}
	return out, err
}

// MaterialDesignOverlayMap 处理多个素材模板合成图片并转换为Map
func (m *sMaterial) MaterialDesignOverlayMap(materials ...models.MaterialDesignOverlayItem) (materialMap map[uint]models.MaterialDesignResultItem, err error) {
	materialMap = make(map[uint]models.MaterialDesignResultItem)
	// 设计图片列表
	resp, err := m.MaterialDesignOverlays(materials...)
	if err != nil {
		return nil, err
	}
	// 转换为Map
	for _, design := range resp {
		materialMap[design.TemplateId] = design
	}
	return
}

// ProcessSingleDesignOverlay 处理并获取单条图片合成设计
func (m *sMaterial) ProcessSingleDesignOverlay(material models.MaterialDesignOverlayItem, imgHandle *img.IHandle) (item *models.MaterialDesignResultItem, err error) {
	if imgHandle == nil {
		imgHandle = img.New()
		// 加载字体文件
		imgHandle.SetFontPath(ifile.SuppIndicator(material.FontPath))
	}

	// 加载背景底图
	imgHandle.SetPath(ifile.SuppIndicator(material.UnderSrc))
	if material.UnderImg != nil {
		imgHandle.SetImg(material.UnderImg)
	}

	// 设置文件保存附件
	imgHandle.SetDir(material.Dir)
	imgHandle.SetFilename(material.Filename)

	// 处理合成素材图片
	overlays := make([]img.IOverlayItem, 0, len(material.DrawMaterialWords))
	for _, drawText := range material.DrawMaterialWords {

		overlays = append(overlays, img.IOverlayItem{
			Src:        ifile.SuppIndicator(drawText.Src),
			PointX:     drawText.MaterialX,
			PointY:     drawText.MaterialY,
			UnderColor: drawText.MaterialColor,
			Opacity:    1,
			DrawText: &img.DrawTextItem{
				Text:     drawText.Text,
				ColorHex: drawText.TextFontColor,
				TextType: drawText.TextType,
				TextX:    drawText.TextX,
				TextY:    drawText.TextY,
				FontSize: drawText.FontSize,
				Sep:      drawText.Sep,
			},
		})
	}
	// 合成图片
	err = imgHandle.Overlay(overlays...)
	if err != nil {
		return nil, err
	}
	// 初始化
	item = &models.MaterialDesignResultItem{
		TemplateId:    material.TemplateId,
		ContentPrefix: imgHandle.Base64Prefix(),
	}
	if !material.IsSave {
		// 读取文件内容
		item.Content = imgHandle.ContentString()
		return
	}
	// 保存文件
	err = imgHandle.Save()
	item.Src = ifile.SlashUploadPath(imgHandle.GetFilePath())
	return
}
